package com.decade.qiyeshapan.handler;


import com.decade.qiyeshapan.service.GameService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.UUID;
import com.decade.qiyeshapan.service.MessageService;
import org.springframework.stereotype.Component;
import java.io.IOException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import java.util.Map;
import java.util.stream.Collectors;
import com.decade.qiyeshapan.entity.User;
import com.decade.qiyeshapan.service.UserService;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.HashMap;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import com.decade.qiyeshapan.config.RedisKeyManager;

@Component
@EnableScheduling
public class MyWebSocketHandler extends TextWebSocketHandler {

    @Autowired
    private MessageService messageService;

    @Autowired
    private UserService userService;

    private final RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private GameService gameService;

    @Autowired
    public MyWebSocketHandler(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    private String generateShortId() {
        return UUID.randomUUID().toString().substring(0, 8);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String socketId = generateShortId(); // 使用自定义短ID
        System.out.println("Connected: " + socketId);
        
        // 存储socketId到session属性
        session.getAttributes().put("socketId", socketId);
        
        // 注册会话到消息服务
        messageService.addSession(session);
        
        String response = String.format("{\"type\":\"socketId\", \"socketId\":\"%s\"}", socketId);
        session.sendMessage(new TextMessage(response));
        
        // 新增：用户连接成功后立即广播玩家状态
        String gameId = (String) session.getAttributes().get("gameId");
        if (gameId != null) {
            messageService.broadcastPlayerStatus(gameId);
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        JSONObject json = JSONUtil.parseObj(payload);
        
        if ("userJoin".equals(json.getStr("type"))) {
            // 广播用户加入消息
            String content = json.getStr("username") + " 加入了游戏";
            broadcastSystemMessage(json.getStr("gameId"), content);
            // 立即广播最新玩家状态
            messageService.broadcastPlayerStatus(json.getStr("gameId"));
        } else if ("taskComplete".equals(json.getStr("type"))) {
            handleTaskComplete(json);
        } else if ("toggleReady".equals(json.getStr("type"))) {
            boolean isReady = json.getBool("isReady");
            String gameId = json.getStr("gameId");
            String username = json.getStr("username");
            
            // 更新准备状态
            userService.toggleReady(gameId, username, isReady);
            
            // 广播玩家状态
            messageService.broadcastPlayerStatus(gameId);
            checkGameStart(gameId);
        } else if ("gameStart".equals(json.getStr("type"))) {
            handleGameStart(json.getStr("gameId"));
        }
    }

    private void broadcastSystemMessage(String gameId, String content) throws IOException {
        JSONObject message = JSONUtil.createObj()
            .set("type", "system")
            .set("content", content)
            .set("timestamp", System.currentTimeMillis());
        
        messageService.broadcastToGame(gameId, message.toString());
    }

    private void saveGameState(String gameId, String username, Object state) {
        String key = RedisKeyManager.userState(gameId, username);
        String timelineKey = RedisKeyManager.timeline(gameId);
        // 直接存储对象，由RedisTemplate处理序列化
        redisTemplate.opsForValue().set(key, state);
        
        // 保存时间线（使用相同序列化方式）
        redisTemplate.opsForValue().set(timelineKey, "第1年 第1季");
    }

    private void handleTaskComplete(JSONObject message) throws IOException {
        // 构造状态对象
        Map<String, Object> state = new HashMap<>();
        state.put("tasks", message.get("tasks"));
        state.put("adData", message.get("adData"));
        state.put("isGameStarted", true);
        
        // 保存状态
        saveGameState(
            message.getStr("gameId"),
            message.getStr("username"),
            state
        );
        
        // 新增通知逻辑
        String content = message.getStr("username") + " 完成了任务: " + message.getStr("taskName");
        broadcastSystemMessage(message.getStr("gameId"), content);
        System.out.println("已广播任务完成通知：" + content);
        
    }

    private void handleGameStart(String gameId) {
        // 保存初始时间线
        String timelineKey = "game:" + gameId + ":timeline";
        redisTemplate.opsForValue().set(timelineKey, "第1年 第1季");
    }

    private void checkGameStart(String gameId) throws IOException {
        JSONObject gameInfo = userService.getGameInfo(gameId);
        if ("running".equals(gameInfo.getStr("status"))) {
            return;
        }
        
        Map<String, User> users = userService.getAllUsers(gameId);
        
        System.out.println("检查游戏开始条件，当前玩家数: " + users.size());
        System.out.println("准备状态: " + users.values().stream()
            .map(u -> u.getUsername() + ":" + u.isReady())
            .collect(Collectors.joining(", ")));

        if(users.size() < 2) {
            System.out.println("玩家人数不足2人");
            return;
        }
        
        boolean allReady = users.values().stream().allMatch(User::isReady);
        
        if(allReady) {
            userService.startGame(gameId);
            new Thread(() -> {
                try {
                    startGameTimer(gameId);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();

            // 广播进度更新
            JSONObject progressMsg = JSONUtil.createObj()
                    .set("type", "progressUpdate")
                    .set("globalProgress", gameService.getGameProgress(gameId)); // 这里需要根据实际进度计算
            messageService.broadcastToGame(gameId, progressMsg.toString());

        } else {
            System.out.println("还有玩家未准备");
        }
    }

    private void startGameTimer(String gameId) throws IOException {
        // 10秒倒计时
        for (int i = 3; i > 0; i--) {
            JSONObject countdownMsg = JSONUtil.createObj()
                .set("type", "countdown")
                .set("remaining", i);
            messageService.broadcastToGame(gameId, countdownMsg.toString());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        // 发送游戏开始消息
        JSONObject startMsg = JSONUtil.createObj()
            .set("type", "gameStart")
            .set("content", "游戏开始！");
        messageService.broadcastToGame(gameId, startMsg.toString());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 移除会话
        messageService.removeSession(session);
        System.out.println("Disconnected: " + session.getId());
    }

    // 修改后的定时任务方法
    @Scheduled(fixedRate = 5000)
    public void broadcastProgressUpdates() {
        // 使用scan命令安全遍历keys
        ScanOptions options = ScanOptions.scanOptions()
                .match("game:*:info")
                .count(100)
                .build();
        
        Cursor<byte[]> cursor = (Cursor<byte[]>) redisTemplate.execute(connection -> {
            return connection.scan(options);
        }, true);

        try {
            while (cursor.hasNext()) {
                String key = new String(cursor.next());
                Map<Object, Object> gameInfo = redisTemplate.opsForHash().entries(key);
                if ("running".equals(gameInfo.get("status"))) {
                    String gameId = key.split(":")[1];
                    int progress = gameService.getGameProgress(gameId);
                    
                    JSONObject progressMsg = JSONUtil.createObj()
                            .set("type", "progressUpdate")
                            .set("globalProgress", progress);
                    messageService.broadcastToGame(gameId, progressMsg.toString());
                }
            }
        } finally {
            cursor.close();
        }
    }
} 